package com.db.manage.service;

import com.db.manage.datasource.DatabaseAdapter;
import com.db.manage.datasource.DynamicDataSource;
import com.db.manage.model.ConnectionConfig;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import javax.sql.DataSource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
@RequiredArgsConstructor
public class ConnectionService {
    @Lazy
    private final DynamicDataSource dynamicDataSource;
    private final List<DatabaseAdapter> databaseAdapters;
    @Lazy
    private final JdbcTemplate jdbcTemplate;
    private final Map<String, DataSource> dataSourceCache = new ConcurrentHashMap<>();

    private static final RowMapper<ConnectionConfig> CONNECTION_CONFIG_MAPPER = (rs, rowNum) -> {
        ConnectionConfig config = new ConnectionConfig();
        config.setId(rs.getString("id"));
        config.setName(rs.getString("name"));
        config.setDbType(rs.getString("db_type"));
        config.setUrl(rs.getString("url"));
        config.setUsername(rs.getString("username"));
        config.setPassword(rs.getString("password"));
        config.setDriverPath(rs.getString("driver_path"));
        config.setVersion(rs.getString("version"));
        config.setActive(rs.getBoolean("active"));
        return config;
    };

    public boolean testConnection(ConnectionConfig config) {
        try {
            log.info("测试连接: {}", config);
            
            // 获取对应的数据库适配器
            DatabaseAdapter adapter = databaseAdapters.stream()
                    .filter(a -> a.getDbType().equals(config.getDbType()))
                    .findFirst()
                    .orElseThrow(() -> new IllegalArgumentException("不支持的数据库类型: " + config.getDbType()));

            // 测试连接
            boolean success = adapter.testConnection(config);
            log.info("连接测试结果: {}", success);
            return success;
        } catch (Exception e) {
            log.error("连接测试失败", e);
            throw e;
        }
    }

    @Transactional
    public void addConnection(ConnectionConfig config) {
        try {
            log.info("添加新连接: {}", config);
            
            // 生成唯一ID
            if (config.getId() == null || config.getId().isEmpty()) {
                config.setId(UUID.randomUUID().toString());
            }

            // 获取对应的数据库适配器
            DatabaseAdapter adapter = databaseAdapters.stream()
                    .filter(a -> a.getDbType().equals(config.getDbType()))
                    .findFirst()
                    .orElseThrow(() -> new IllegalArgumentException("不支持的数据库类型: " + config.getDbType()));

            // 测试连接
            if (!adapter.testConnection(config)) {
                throw new IllegalArgumentException("无法连接到数据库，请检查连接信息");
            }

            // 创建数据源
            DataSource dataSource = adapter.createDataSource(config);
            log.info("数据源创建成功");

            // 保存到数据库
            jdbcTemplate.update(
                "INSERT INTO connection_config (id, name, db_type, url, username, password, driver_path, version, active) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
                config.getId(),
                config.getName(),
                config.getDbType(),
                config.getUrl(),
                config.getUsername(),
                config.getPassword(),
                config.getDriverPath(),
                config.getVersion(),
                config.isActive()
            );
            log.info("连接配置已保存到数据库");

            // 更新动态数据源
            Map<Object, Object> targetDataSources = dynamicDataSource.getTargetDataSources();
            targetDataSources.put(config.getId(), dataSource);
            dynamicDataSource.setTargetDataSources(targetDataSources);
            dynamicDataSource.afterPropertiesSet();
            log.info("动态数据源已更新");

            // 缓存数据源
            dataSourceCache.put(config.getId(), dataSource);
            log.info("数据源已缓存");
        } catch (Exception e) {
            log.error("添加连接失败: {}", config, e);
            throw e;
        }
    }

    @Transactional
    public void removeConnection(String connectionId) {
        try {
            log.info("删除连接: {}", connectionId);
            
            // 从数据库删除
            jdbcTemplate.update("DELETE FROM connection_config WHERE id = ?", connectionId);
            log.info("连接配置已从数据库删除");

            // 从动态数据源中移除
            Map<Object, Object> targetDataSources = dynamicDataSource.getTargetDataSources();
            targetDataSources.remove(connectionId);
            dynamicDataSource.setTargetDataSources(targetDataSources);
            dynamicDataSource.afterPropertiesSet();
            log.info("连接已从动态数据源中移除");

            // 从缓存中移除
            dataSourceCache.remove(connectionId);
            log.info("连接已从缓存中移除");
        } catch (Exception e) {
            log.error("删除连接失败: {}", connectionId, e);
            throw e;
        }
    }

    public JdbcTemplate switchConnection(String connectionId) {
        try {
            log.info("开始切换数据源到: {}", connectionId);

            if (!dataSourceCache.containsKey(connectionId)) {
                log.error("连接不存在: {}", connectionId);
                throw new IllegalArgumentException("连接不存在: " + connectionId);
            }
            
            // 获取目标数据源
            DataSource targetDataSource = dataSourceCache.get(connectionId);
            if (targetDataSource == null) {
                log.error("目标数据源为空: {}", connectionId);
                throw new IllegalArgumentException("目标数据源为空: " + connectionId);
            }
            
            // 切换数据源
            dynamicDataSource.setCurrentLookupKey(connectionId);
            dynamicDataSource.afterPropertiesSet();
            
            // 验证切换是否成功
            try {
                JdbcTemplate tempJdbcTemplate = new JdbcTemplate(dynamicDataSource);
                tempJdbcTemplate.execute("SELECT 1");
                log.info("数据源切换成功，验证查询通过");
                log.info("数据源切换完成: {}", connectionId);
                return tempJdbcTemplate;
            } catch (Exception e) {
                log.error("数据源切换验证失败", e);
                throw new RuntimeException("数据源切换验证失败: " + e.getMessage());
            }

        } catch (Exception e) {
            log.error("切换连接失败: {}", connectionId, e);
            throw e;
        }
    }

    public List<ConnectionConfig> getAllConnections() {
        try {
            // dynamicDataSource.setCurrentLookupKey("default");
            // JdbcTemplate jdbcTemplate = switchConnection("default");
            List<ConnectionConfig> connections = jdbcTemplate.query("SELECT * FROM connection_config", CONNECTION_CONFIG_MAPPER);
            log.info("获取到 {} 个连接配置", connections.size());
            return connections;
        } catch (Exception e) {
            log.error("获取连接配置失败", e);
            throw e;
        }
    }
} 